<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class IdCard implements Rule
{
    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param string $attribute
     * @param mixed $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        return $this->validator($value);
    }

    /**
     * @param $value
     * @return bool
     */
    public function validator($value)
    {
        if (18 != strlen($value)) {
            return false;
        }

        $weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];

        $code = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];

        $mode = 0;

        // 取最后一位
        $ver = substr($value, -1);
        if ($ver == 'x') {
            $ver = 'X';
        }

        foreach ($weight as $key => $val) {
            if ($key == 17) {
                continue;
            }
            // 取第一位
            $digit = intval(substr($value, $key, 1));

            $mode += $digit * $val;
        }

        $mode %= 11;

        if ($ver != $code[$mode]) {
            return false;
        }

        // 获取年月日
        list($month, $day, $year) = self::getMDYFromCard($value);

        $check = checkdate($month, $day, $year);

        if (!$check) {
            return false;
        }

        $today = date('Ymd');
        $date = substr($value, 6, 8);

        if ($date >= $today) {
            return false;
        }

        return true;
    }

    private function getMDYFromCard($value)
    {
        $date = substr($value, 6, 8);
        $year = substr($date, 0, 4);
        $month = substr($date, 4, 2);
        $day = substr($date, 6);
        return [$month, $day, $year];
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return ':attribute 不合法.';
    }
}
